"""
OCR工具模块 - 处理身份证OCR识别逻辑
"""

# 导入标准库
import base64  # 用于Base64编码/解码
import re  # 用于正则表达式处理
from typing import Optional, Dict  # 用于类型提示

# 导入第三方库
import httpx  # 异步HTTP客户端

# 导入项目内部模块
from config import settings  # 应用配置
from tools.baidu_ocr_client import idcard  # 百度OCR客户端


async def ocr_id_card(
    image_base64: Optional[str] = None,
    image_url: Optional[str] = None,
    card_side: str = "front"
) -> Optional[Dict]:
    """
    身份证OCR识别主函数
    
    参数:
        image_base64: 图片的Base64编码（可选）
        image_url: 图片的URL地址（可选）
        card_side: 身份证的正反面，"front"或"back"
        
    返回:
        识别结果字典，如果失败则返回None
    """
    try:
        # 检查参数有效性
        if not image_base64 and not image_url:
            print("[错误] 必须提供 image_base64 或 image_url 其中之一")
            return None

        # 如果提供了Base64图片数据
        if image_base64:
            # 检查并处理Base64数据前缀
            if image_base64.startswith('data:image'):
                # 如果是完整的Data URL，提取Base64部分
                # 例如: ...
                image_base64 = image_base64.split(',')[1]
            
            # 验证Base64格式
            try:
                # 尝试解码Base64数据以验证其有效性
                base64.b64decode(image_base64)
            except Exception as e:
                print(f"[错误] Base64数据无效: {e}")
                return None
            
            # 调用百度OCR进行识别
            return await _call_baidu_ocr_with_base64(image_base64, card_side)
        
        # 如果提供了图片URL
        elif image_url:
            # 验证URL格式
            url_pattern = re.compile(
                r'^https?://'  # http:// 或 https://
                r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+[A-Z]{2,6}\.?|'  # 域名
                r'localhost|'  # localhost
                r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})'  # IP地址
                r'(?::\d+)?'  # 可选端口号
                r'(?:/?|[/?]\S+)$', re.IGNORECASE)
            
            # 检查URL格式是否有效
            if not url_pattern.match(image_url):
                print(f"[错误] URL格式无效: {image_url}")
                return None
            
            # 调用百度OCR进行识别
            return await _call_baidu_ocr_with_url(image_url, card_side)
        
        # 如果既没有Base64也没有URL
        else:
            print("[错误] 必须提供 image_base64 或 image_url 其中之一")
            return None
            
    except Exception as e:
        # 捕获并打印异常
        print(f"[错误] OCR处理异常: {e}")
        import traceback
        traceback.print_exc()
        return None


async def _call_baidu_ocr_with_base64(image_base64: str, card_side: str) -> Optional[Dict]:
    """
    使用Base64图片数据调用百度OCR（内部函数）
    
    参数:
        image_base64: 图片的Base64编码
        card_side: 身份证的正反面，"front"或"back"
        
    返回:
        识别结果字典，如果失败则返回None
    """
    try:
        # 构造百度OCR API的URL
        url = "https://aip.baidubce.com/rest/2.0/ocr/v1/idcard"
        
        # 获取访问令牌
        access_token = idcard.get_access_token()
        if not access_token:
            print("[错误] 无法获取百度OCR访问令牌")
            return None
        
        # 在URL中添加访问令牌参数
        url += f"?access_token={access_token}"
        
        # 构造请求参数
        params = {
            'id_card_side': card_side,      # 身份证正反面
            'image': image_base64,          # 图片Base64数据
            'detect_direction': 'false',    # 是否检测图像朝向
            'detect_risk': 'false',         # 是否开启身份证风险类型功能
            'detect_photo': 'false',        # 是否检测头像
            'detect_card': 'false'          # 是否检测身份证边框
        }
        
        # 将参数转换为URL编码的表单数据
        form_data = '&'.join([f'{k}={v}' for k, v in params.items()])
        
        # 使用httpx异步客户端发送POST请求
        async with httpx.AsyncClient(timeout=30.0) as client:
            response = await client.post(
                url,
                data=form_data,
                headers={"Content-Type": "application/x-www-form-urlencoded"}
            )
            
            # 检查响应状态码
            if response.status_code == 200:
                # 解析响应JSON
                result = response.json()
                
                # 检查是否有错误
                if "error_code" in result:
                    print(f"[错误] 身份证识别失败: {result.get('error_msg', '未知错误')}")
                    return None
                
                # 解析识别结果
                words_result = result.get("words_result", {})
                
                # 打印原始识别结果，方便调试查看所有字段
                print(f"[OCR调试] 百度OCR返回的原始字段: {list(words_result.keys())}")
                
                # 根据正反面分别处理结果
                if card_side == "front":
                    # 正面信息
                    # 注意：百度OCR可能返回不同的字段名，需要根据实际情况调整
                    ocr_result = {
                        "name": words_result.get("姓名", {}).get("words", ""),
                        "id_card_num": words_result.get("公民身份号码", {}).get("words", ""),
                        "gender": words_result.get("性别", {}).get("words", ""),
                        "nation": words_result.get("民族", {}).get("words", ""),
                        "birth": words_result.get("出生", {}).get("words", ""),
                        "address": words_result.get("住址", {}).get("words", "")
                    }
                else:
                    # 反面信息
                    ocr_result = {
                        "issuing_authority": words_result.get("签发机关", {}).get("words", ""),
                        "valid_date": words_result.get("失效日期", {}).get("words", "") + 
                                     "-" + words_result.get("签发日期", {}).get("words", "")
                    }
                
                # 打印识别结果
                print(f"[OCR成功] 识别结果: {ocr_result}")
                return ocr_result
            else:
                # HTTP请求失败
                print(f"[错误] HTTP请求失败: {response.status_code}")
                print(f"响应内容: {response.text}")
                return None
                
    except Exception as e:
        # 捕获并打印异常
        print(f"[错误] 调用百度OCR异常: {e}")
        import traceback
        traceback.print_exc()
        return None


async def _call_baidu_ocr_with_url(image_url: str, card_side: str) -> Optional[Dict]:
    """
    使用图片URL调用百度OCR（内部函数）
    
    参数:
        image_url: 图片的URL地址
        card_side: 身份证的正反面，"front"或"back"
        
    返回:
        识别结果字典，如果失败则返回None
    """
    try:
        # 构造百度OCR API的URL
        url = "https://aip.baidubce.com/rest/2.0/ocr/v1/idcard"
        
        # 获取访问令牌
        access_token = idcard.get_access_token()
        if not access_token:
            print("[错误] 无法获取百度OCR访问令牌")
            return None
        
        # 在URL中添加访问令牌参数
        url += f"?access_token={access_token}"
        
        # 构造请求参数
        params = {
            'id_card_side': card_side,      # 身份证正反面
            'url': image_url,               # 图片URL
            'detect_direction': 'false',    # 是否检测图像朝向
            'detect_risk': 'false',         # 是否开启身份证风险类型功能
            'detect_photo': 'false',        # 是否检测头像
            'detect_card': 'false'          # 是否检测身份证边框
        }
        
        # 将参数转换为URL编码的表单数据
        form_data = '&'.join([f'{k}={v}' for k, v in params.items()])
        
        # 使用httpx异步客户端发送POST请求
        async with httpx.AsyncClient(timeout=30.0) as client:
            response = await client.post(
                url,
                data=form_data,
                headers={"Content-Type": "application/x-www-form-urlencoded"}
            )
            
            # 检查响应状态码
            if response.status_code == 200:
                # 解析响应JSON
                result = response.json()
                
                # 检查是否有错误
                if "error_code" in result:
                    print(f"[错误] 身份证识别失败: {result.get('error_msg', '未知错误')}")
                    return None
                
                # 解析识别结果
                words_result = result.get("words_result", {})
                
                # 打印原始识别结果，方便调试查看所有字段
                print(f"[OCR调试] 百度OCR返回的原始字段: {list(words_result.keys())}")
                
                # 根据正反面分别处理结果
                if card_side == "front":
                    # 正面信息
                    ocr_result = {
                        "name": words_result.get("姓名", {}).get("words", ""),
                        "id_card_num": words_result.get("公民身份号码", {}).get("words", ""),
                        "gender": words_result.get("性别", {}).get("words", ""),
                        "nation": words_result.get("民族", {}).get("words", ""),
                        "birth": words_result.get("出生", {}).get("words", ""),
                        "address": words_result.get("住址", {}).get("words", "")
                    }
                else:
                    # 反面信息
                    ocr_result = {
                        "issuing_authority": words_result.get("签发机关", {}).get("words", ""),
                        "valid_date": words_result.get("失效日期", {}).get("words", "") + 
                                     "-" + words_result.get("签发日期", {}).get("words", "")
                    }
                
                # 打印识别结果
                print(f"[OCR成功] 识别结果: {ocr_result}")
                return ocr_result
            else:
                # HTTP请求失败
                print(f"[错误] HTTP请求失败: {response.status_code}")
                print(f"响应内容: {response.text}")
                return None
                
    except Exception as e:
        # 捕获并打印异常
        print(f"[错误] 调用百度OCR异常: {e}")
        import traceback
        traceback.print_exc()
        return None